﻿using System;
using System.Configuration;
using System.IO;
using System.Web;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Unity;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;

namespace SPFluid.Core.HttpModules
{
    public class SPFluidHttpModule : IHttpModule
    {
        private const string UnitySectionName = "unity";

        void IHttpModule.Init(HttpApplication context)
        {
            var uri = context.Request.Url;
            using (var site = new SPSite(uri.AbsoluteUri))
            using (var web = site.OpenWeb())
            {
                var container = new UnityContainer();

                var enterpriseLibraryConfigPath = this.GetEnterpriseLibraryConfigPath(web);
                if (!string.IsNullOrEmpty(enterpriseLibraryConfigPath))
                {
                    this.ConfigureEnterpriseLibrary(enterpriseLibraryConfigPath, container);
                }

                var modulesConfigPath = this.GetModulesConfigPath(web);
                if (!string.IsNullOrEmpty(modulesConfigPath))
                {
                    this.ConfigureModules(modulesConfigPath, container);
                }

                var unityServiceLocator = new UnityServiceLocator(container);
                ServiceLocator.SetLocatorProvider(() => unityServiceLocator);
            }
        }

        void IHttpModule.Dispose()
        {
        }

        private void ConfigureEnterpriseLibrary(string enterpriseLibraryConfigPath, IUnityContainer container)
        {
            var builder = new ConfigurationSourceBuilder();
            builder.ConfigureCaching().ForCacheManagerNamed("SPFluid").UseAsDefaultCache().StoreInMemory();

            var configSource = new DictionaryConfigurationSource();
            builder.UpdateConfigurationWithReplace(configSource);

            var coreExtension = new EnterpriseLibraryCoreExtension(configSource);
            container.AddExtension(coreExtension);
        }

        private void ConfigureModules(string modulesConfigPath, IUnityContainer container)
        {
            var modulesSetupPath = SPUtility.GetGenericSetupPath(modulesConfigPath);
            var directory = new DirectoryInfo(modulesSetupPath);
            var fileInfos = directory.GetFiles("*.config", SearchOption.TopDirectoryOnly);
            foreach (var fileInfo in fileInfos)
            {
                var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = fileInfo.FullName };
                var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                var unitySection = (UnityConfigurationSection)configuration.GetSection(UnitySectionName);
                unitySection.Configure(container);
            }
        }

        private string GetEnterpriseLibraryConfigPath(SPWeb web)
        {
            return this.GetConfigPath(web, Constants.EnterpriseLibraryConfigPathKey);
        }

        private string GetModulesConfigPath(SPWeb web)
        {
            return this.GetConfigPath(web, Constants.ModulesConfigPathKey);
        }

        private string GetConfigPath(SPWeb web, string key)
        {
            var configPath = Convert.ToString(web.AllProperties[key]);
            if (string.IsNullOrEmpty(configPath))
            {
                configPath = Convert.ToString(web.Site.RootWeb.AllProperties[key]);
            }

            return configPath;
        }
    }
}